package inf.loansManagement;

import inf.hibernateUtils.HibernateUtil;

import java.io.Serializable;
import java.util.Calendar;
import java.util.GregorianCalendar;

import javax.persistence.*;

import org.hibernate.Session;

import inf.exceptions.BadParametersException;
import inf.exceptions.AllSpecimensBooked;

import inf.specimensManagement.Specimen;
import inf.mediasManagement.Media;
import inf.subscribersManagement.Subscriber;

import inf.main.Constraints;

/** 
* @author Fabre, Malric
*/
@Entity
@Table(name="bookings")
public class Booking implements java.lang.Comparable {

	/**
	 * @uml.property  name="id"
	 */
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name="id", unique = true, nullable = false)
	private long id;
	
	private Calendar creationDate;
	/**
	 * @uml.property  name="beginAvalaibilityDate"
	 */
	private Calendar beginAvalaibilityDate;

	/**
	 * @uml.property  name="endAvailibilityDate"
	 */
	private Calendar endAvailibilityDate;

	/**
	 * @uml.property  name="specimen"
	 * @uml.associationEnd  
	 */
	@OneToOne
	private Specimen specimen;

	@ManyToOne
	private Media media;
	
	/**
	 * @uml.property  name="subscriber"
	 * @uml.associationEnd  
	 */
	@ManyToOne
	private Subscriber subscriber;

	public Booking (){}
	
	// Creer une reservation sur un media
	public Booking(Media media, Subscriber subscriber) throws BadParametersException {
		if ((media == null) || (subscriber == null))
			throw new BadParametersException();
		
		this.setMedia(media);
		this.setSubscriber(subscriber);
		this.setSpecimen(null);

		this.creationDate = new GregorianCalendar();
		this.beginAvalaibilityDate = null;
		this.endAvailibilityDate = null;		
		
		inf.loansManagement.BookingDAO.save(this);
	}

	public void startBooking() {
		beginAvalaibilityDate = new GregorianCalendar();
		endAvailibilityDate = new GregorianCalendar();
		endAvailibilityDate.add(Calendar.DATE, Constraints.bookingDELAY);

		this.specimen.setBooking(this);

		inf.loansManagement.BookingDAO.save(this);
	}

	public void endBooking() throws BadParametersException {
		this.subscriber.endBooking(this);
		this.specimen.setBooking(null);

		inf.subscribersManagement.SubscriberDAO.save(this.subscriber);
		inf.mediasManagement.MediaDAO.save(this.specimen.getMedia());
		
		inf.loansManagement.BookingDAO.remove(this);		
	}

	/**
	 * Getter of the property <tt>beginAvalaibilityDate</tt>
	 * @return  Returns the beginAvalaibilityDate.
	 * @uml.property  name="beginAvalaibilityDate"
	 */
	public Calendar getBeginAvalaibilityDate() {
		return beginAvalaibilityDate;
	}

	/**
	 * Setter of the property <tt>beginAvalaibilityDate</tt>
	 * @param beginAvalaibilityDate  The beginAvalaibilityDate to set.
	 * @uml.property  name="beginAvalaibilityDate"
	 */
	public void setBeginAvalaibilityDate(Calendar beginAvalaibilityDate) {
		this.beginAvalaibilityDate = beginAvalaibilityDate;
	}

	/**
	 * Getter of the property <tt>endAvailibilityDate</tt>
	 * @return  Returns the endAvailibilityDate.
	 * @uml.property  name="endAvailibilityDate"
	 */
	public Calendar getEndAvailibilityDate() {
		return endAvailibilityDate;
	}

	/**
	 * Setter of the property <tt>endAvailibilityDate</tt>
	 * @param endAvailibilityDate  The endAvailibilityDate to set.
	 * @uml.property  name="endAvailibilityDate"
	 */
	public void setEndAvailibilityDate(Calendar endAvailibilityDate) {
		this.endAvailibilityDate = endAvailibilityDate;
	}

	public Specimen getSpecimen() {
		return this.specimen;
	
	}

	public void setSpecimen(Specimen specimen) {
		this.specimen = specimen;
	}

	public Media getMedia() {
		return this.media;
	
	}
	public void setMedia(Media media) {
		this.media = media;
	}
	
	/**
	 * @uml.property  name="subscriber"
	 * @uml.associationEnd  inverse="reservations:subscribersManagement.Subscriber"
	 */
	

	public Subscriber getSubscriber() {
		return subscriber;
	}

	public void setSubscriber(Subscriber subscriber) {
		this.subscriber = subscriber;
	}

	public Calendar getCreationDate(){
		return this.creationDate;
	}

	public void setCreationDate(Calendar date){
		this.creationDate = date;
	}
	
	public boolean equals(Object o) {
		if (this == o)
			return true;
		else
			return false;
	}
	
	public int hashCode() {
		return (int) id;
	}

	public int compareTo(Object other) { 
		Booking bookingOther = (Booking) other;
		return this.creationDate.compareTo(bookingOther.getCreationDate());
	}

	public long getId() {
		return id;
	} 
}

